package com.iaz.tech.tools.ai.neuron.runtime.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.iaz.tech.tools.ai.neuron.runtime.NeuronRuntime;
import com.iaz.tech.tools.common.utils.FileTools;
import com.iaz.tech.tools.common.utils.UtilTools;
import com.iaz.tech.tools.message.IMessageAble;
import com.iaz.tech.tools.message.impl.MessageForAnswer;
import com.iaz.tech.tools.message.impl.MessageForAsk;
import com.iaz.tech.tools.message.impl.MessageForState;
import com.iaz.tech.tools.message.impl.MessageForTalk;
import com.iaz.tech.tools.mq.AZIMessageContainer;
import com.iaz.tech.tools.mq.IMessageSectionAbility;
import com.iaz.tech.tools.property.project.Project;
import com.iaz.tech.tools.uml.IUMLNeuronAble;
import com.iaz.tech.tools.uml.file.impl.UMLLoaderFactory;
import com.iaz.tech.tools.uml.structural.classstruct.impl.NeuronClassStruct;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.iaz.tech.tools.ai.neuron.ability.INeuronAbility; 
import com.iaz.tech.tools.ai.neuron.cell.NeuronCell;

import lombok.Data;
import lombok.EqualsAndHashCode;

/**
 * 神经元世界
 */
@EqualsAndHashCode(callSuper=false)
@Data
public class NeuronsWorld extends NeuronRuntime {
	
	/**
     * 日志
     */
	private final static Logger logger = (Logger) LoggerFactory.getLogger(NeuronsWorld.class);
	/**
	 * 消息队列
	 */
	private IMessageSectionAbility messageMQ = new AZIMessageContainer();
	
	/**
	 * 神经元
	 */
	private List<INeuronAbility> neurons = new ArrayList<INeuronAbility>();


	public void pushNeuron(INeuronAbility neuron) {
		try {
			if (neuron == null) {
				throw new IllegalArgumentException("neuron不能为null");
			}
			neuron.pushRuntime(this);
			this.neurons.add(neuron);
		} catch(Exception e) {
			logger.error("出现异常：" + e.getMessage());
		}
		
	}

	/**
	 * 根据类名查找神经元
	 */
	@Override
	public INeuronAbility findByClassName(String className) {
		INeuronAbility result = null;
		try {
			if (UtilTools.IsNull(className)) {
				throw new Exception("入口参数className为空。");
			}
			
			for (int i = 0; i < this.neurons.size(); i++){
				INeuronAbility neuron = this.neurons.get(i);
				if (neuron == null){
					continue;
				}
				
				if (neuron instanceof NeuronCell) {
					NeuronCell cell = (NeuronCell)neuron;
					
					if (cell.getUseCase() == null ){
						continue;
					}

					if (cell.getUseCase() instanceof NeuronClassStruct) {
						NeuronClassStruct classStruct = (NeuronClassStruct)cell.getUseCase();
						if (classStruct.getName().equals(className)) {
							result = cell;
							break;
						}
					}
				}
			}

		} catch (Exception e) {
			logger.error("出现异常：" + e.getMessage());
		}		
		return result;
	}

	@Override
	public INeuronAbility findByName(String name) {
		INeuronAbility result = null;
		try {
			if (UtilTools.IsNull(name)) {
				throw new Exception("入口参数name为空。");
			}
			if (UtilTools.IsNull(name)) {
				throw new Exception("入口参数name为空。");
			}
			String tmpName = UtilTools.Trim(name);
			for (int i = 0; i < this.neurons.size(); i++){
				INeuronAbility neuron = this.neurons.get(i);
				if (neuron == null){
					continue;
				}
				
				if (neuron instanceof NeuronCell) {
					NeuronCell neuronCell = (NeuronCell)neuron;
					if (neuronCell.getUseCase() == null){
						continue;
					}
					if (neuronCell.getUseCase() instanceof NeuronClassStruct) {
						NeuronClassStruct classStruct = (NeuronClassStruct)neuronCell.getUseCase();
						if (classStruct.getName().equals(tmpName)) {
							result = neuron;
							break;
						}
					} else {

					}
				}
			}
		} catch (Exception e) {
			logger.error("出现异常：" + e.getMessage());
		}		
		return result;
	}

	@Override
	public INeuronAbility findByUUID(UUID id) {
		INeuronAbility result = null;
		try {
			if (id == null) {
				throw new Exception("入口参数id为空。");
			}
			
			for (int i = 0; i < this.neurons.size(); i++){
				INeuronAbility neuron = this.neurons.get(i);
				if (neuron == null){
					continue;
				}
				UUID uuid = neuron.forNeuronID();
				if (uuid == null){
					continue;
				}
				if (uuid.equals(id)) {
					result = neuron;
					break;
				}
			}
			
		} catch (Exception e) {
			logger.error("出现异常：" + e.getMessage());
		}		
		return result;
	}

	@Override
	public IMessageSectionAbility findMQ() {
		try {
			return this.messageMQ;
		} catch(Exception e) {
			logger.error("执行Message Queue 异常：" + e.getMessage());
		}
		return null;
	}
	
	/**
	 * 加载神经元程序
	 */
	@Override
	public void load(String path) {
		try {
			/* 文件列表 */
			if (UtilTools.IsNull(path)) {
				throw new Exception("入口参数path 为空，没有指定。");
			}
			List<String> files = FileTools.lstFiles(path, "uml");
			if (files == null) {
				throw new Exception("异常：files 没有指定。" );
			}
			if (files.size() == 0) {
				throw new Exception("files 没有指定, path:"  + path + "为空。"); 
			}			
			/* 从文件加载Neuron *.num  */
			for (int i =0; i < files.size(); i++) {
				String file_path = files.get(i);
				if (UtilTools.IsNull(file_path)) {
					continue;
				}
				System.out.println("加载文件：" + file_path);
				System.out.println("加载文件：" + path + "\\" + file_path);
				 
				this.loadUMLFile( path + "\\" + file_path); 
			}
			
		} catch(Exception e) {
			logger.error("异常：" + e.getMessage());
		}
	}
	/**
	 * 加载UML 文件
	 * @param file
	 */
	public void loadUMLFile(String file) {
		try {
			if (UtilTools.IsNull(file)) {
				throw new Exception("文件file 没有指定。");
			}

			String fileContent = FileTools.getFileData(file);
			if (UtilTools.IsNull(fileContent)) {
				throw new Exception("读取UML 文件失败。");
			}
			/* 将JSON 字符串，转换成类 */
			JSONObject json_obj = JSON.parseObject(fileContent);
			if (json_obj == null) {
				throw new Exception("转换JSON Object 失败！");
			}

			/* 初始化Object */
			if (!json_obj.containsKey("modules")) {
				return;
			}
			/* 依次读取UML 的配置，用来生成Neuron Cell 部分，并建立起来显 */
			JSONArray json_array = json_obj.getJSONArray("modules");
			if (json_array == null) {
				throw new Exception("配置出现异常，其中Modules 成员为空。");
			}

			for (int i = 0; i <json_array.size(); i++ ) {
				JSONObject _child_json_obj = json_array.getJSONObject(i);
				if (_child_json_obj == null ) {
					logger.error("json obj 对应对象为空，请检查配置项目。");
					continue;
				}
				IUMLNeuronAble uml = UMLLoaderFactory.generateUML(_child_json_obj);
				if (uml == null) {
					logger.error("生成UML 对象失败，请检查配置项目。");
					continue;
				}
				/* 注册到世界 */
				NeuronCell new_neuron = new NeuronCell();
				new_neuron.setUseCase(uml);
				new_neuron.setRuntime(this);
				this.neurons.add(new_neuron);				
			}
		} catch(Exception e ){
			logger.error("出现异常：" + e.getMessage());
		}
	}
	/**
	 * 发送消息到项目
	 * @param project
	 * @param msg
	 */
	public void sendMessage(Project project, IMessageAble msg) {
		try {
			if (project == null) {
				throw new Exception("入口参数project 为空。");
			}
			if (msg == null) {
				throw new Exception("入口参数msg 为空。");
			}
			/* 发送消息 */
			if (msg instanceof MessageForAnswer) {
				MessageForAnswer neuronMsg = (MessageForAnswer)msg;
				neuronMsg.setProjectId(project.getProjectID());
			} else if (msg instanceof MessageForAsk) {
				MessageForAsk neuronMsg = (MessageForAsk)msg;
				neuronMsg.setProjectId(project.getProjectID());
			}else if (msg instanceof MessageForState) {
				MessageForState neuronMsg = (MessageForState)msg;
				neuronMsg.setProjectId(project.getProjectID());
			}else if (msg instanceof MessageForTalk) {
				MessageForTalk neuronMsg = (MessageForTalk)msg;
				neuronMsg.setProjectId(project.getProjectID());
				if (UtilTools.IsNull(neuronMsg.getTalk())) {
					return;
				}
				String talk_man = UtilTools.Trim(neuronMsg.getTalk());
				INeuronAbility neuron = this.findByName(talk_man);
				if (neuron == null) {
					return;
				}
				neuron.talkMe(msg);
			}
		} catch(Exception e){
			logger.error("出现异常：" + e.getMessage());
		}
	}
}
